use std::{
    collections::HashMap, fs::{self, File}, io::{BufRead, BufReader, Error, ErrorKind, Read, Write}, path::{self, Path}
};

use clap::Parser;

use ui::cui::ProgressBar;
use util::listener::{M3u8ChunkListener, M3u8Listener};
use util::{write, History, ProgressMonitor};

use crate::util::ffmpeg_convert;

mod ui;
mod util;

#[derive(Parser, Debug)]
#[clap(name = "fetch-m3u8", author = "codimiracle <codimiracle@outlook.com>", version = "1.0", about = "fetch m3u8 video and merge.", long_about = None)]
struct Args {
    /// url to fetch m3u8, like http://example.com/index.m3u8
    url: String,
    /// video saved path.
    path: String,
}

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let args = Args::parse();
    fs::create_dir_all(args.path.as_str()).unwrap();

    let mut history_path = String::from(args.path.as_str());
    history_path.push(path::MAIN_SEPARATOR);
    history_path.push_str(".history.json");

    let mut history = History::load(history_path.as_str());

    let mut listener = M3u8Listener::new(args.path.as_str(), &history);
    let result = write(
        args.url.as_str(),
        args.path.as_str(),
        &mut listener,
        &mut history,
    )
    .await;
    // download key.
    if !listener.key_url.is_empty() {
        let mut key_listener = M3u8ChunkListener::new(&history);
        let result = write(
            listener.key_url.as_str(),
            args.path.as_str(),
            &mut key_listener,
            &mut history,
        )
        .await;

        if listener.encrypted_method == "aes-128" {}
    }

    // download chunk.
    let total_chunks = listener.chunk_list.len();
    println!("total {} chuncks", total_chunks);
    let mut chunk_files: Vec<String> = Vec::new();

    let mut current_chunk = 0;
    for url in listener.chunk_list {
        current_chunk += 1;
        println!("downloading {}/{} chunck...", current_chunk, total_chunks);
        let mut chunk_listener = M3u8ChunkListener::new(&history);
        let result = write(
            url.as_str(),
            args.path.as_str(),
            &mut chunk_listener,
            &mut history,
        )
        .await;
        let chunk_file = String::from(chunk_listener.destination.as_str());
        chunk_files.push(chunk_file);
    }
    //merge chunk.
    let mut merge_file_path = String::from(args.path.as_str());
    merge_file_path.push(path::MAIN_SEPARATOR);
    merge_file_path.push_str("merge.mp4");

    println!("ffmpeg converting...");

    ffmpeg_convert(
        listener.index_redirected_path.as_str(),
        merge_file_path.as_str(),
    );
    Ok(())
}
